#ifndef __drv_l2_USBH_UVC_H__
#define __drv_l2_USBH_UVC_H__

#include "drv_l1_usbh.h"
#define FORMAT_YUV2		1
#define FORMAT_NV12		2
#define FORMAT_MJPGE	3

#define FRAME_WIDTH_1080P	1920
#define FRAME_HEIGHT_1080P	1080
#define FRAME_WIDTH_720P	1280
#define FRAME_HEIGHT_720P	720
#define FRAME_WIDTH_VGA	640
#define FRAME_HEIGHT_VGA	480

#define GUID_YUV2_0		0x32595559
#define GUID_YUV2_1		0x0000
#define GUID_YUV2_2		0x0010
#define GUID_YUV2_3		0x8000
#define GUID_YUV2_4		0x00AA00
#define GUID_YUV2_5		0x389B71

#define GUID_NV12_0		0x3231564E
#define GUID_NV12_1		0x0000
#define GUID_NV12_2		0x0010
#define GUID_NV12_3		0x8000
#define GUID_NV12_4		0x00AA00
#define GUID_NV12_5		0x389B71

#define UVC_MAX_FORMAT	4
#define UVC_MAX_FRAME	10

/* USB descriptor types */
typedef enum
{
	UVC_DATA_UNCOMPRESSED_YUV2	= 1,
	UVC_DATA_UNCOMPRESSED_NV12,
	UVC_DATA_MJPEG
} UVC_DATA_FORMAT;

/* Video Class-Specific Request Codes, (USB_Video_Class_1.1.pdf, A.8 Video Class-Specific Request Codes) */
#define RC_UNDEFINED	0x00
#define SET_CUR			0x01
#define GET_CUR			0x81
#define GET_MIN			0x82
#define GET_MAX			0x83
#define GET_RES			0x84
#define GET_LEN			0x85
#define GET_INFO		0x86
#define GET_DEF			0x87

// Video Class-Specific VideoStreaming Interface Descriptor Subtypes, (USB_Video_Class_1.1.pdf, A.6 Video Class-Specific VS Interface Descriptor Subtypes) */
#define VS_UNDEFINED			0x00
#define VS_INPUT_HEADER			0x01
#define VS_OUTPUT_HEADER		0x02
#define VS_STILL_IMAGE_FRAME	0x03
#define VS_FORMAT_UNCOMPRESSED	0x04
#define VS_FRAME_UNCOMPRESSED	0x05
#define VS_FORMAT_MJPEG			0x06
#define VS_FRAME_MJPEG			0x07
#define VS_FORMAT_MPEG2TS		0x0A
#define VS_FORMAT_DV			0x0C
#define VS_COLORFORMAT			0x0D
#define VS_FORMAT_FRAME_BASED	0x10
#define VS_FRAME_FRAME_BASED	0x11
#define VS_FORMAT_STREAM_BASED	0x12

/* VideoStreaming Interface Control Selectors, (USB_Video_Class_1.1.pdf, A.9.7 VideoStreaming Interface Control Selectors) */
#define VS_CONTROL_UNDEFINED			0x00
#define VS_PROBE_CONTROL				0x01
#define VS_COMMIT_CONTROL				0x02
#define VS_STILL_PROBE_CONTROL			0x03
#define VS_STILL_COMMIT_CONTROL			0x04
#define VS_STILL_IMAGE_TRIGGER_CONTROL	0x05
#define VS_STREAM_ERROR_CODE_CONTROL	0x06
#define VS_GENERATE_KEY_FRAME_CONTROL	0x07
#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08

/* VideoStreaming Interface Control Selectors, (USB_Video_Class_1.1.pdf, A.9.7 VideoStreaming Interface Control Selectors) */
#define VS_CONTROL_UNDEFINED			0x00
#define VS_PROBE_CONTROL				0x01
#define VS_COMMIT_CONTROL				0x02
#define VS_STILL_PROBE_CONTROL			0x03
#define VS_STILL_COMMIT_CONTROL			0x04
#define VS_STILL_IMAGE_TRIGGER_CONTROL	0x05
#define VS_STREAM_ERROR_CODE_CONTROL	0x06
#define VS_GENERATE_KEY_FRAME_CONTROL	0x07
#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08

#define TD_NO_INTERRUPT_DELAY			0x07

#define UVC_FOR_FPGA					1		/* For FPGA test */
#if(UVC_FOR_FPGA)
#define HC_UVC_ITD_FRAME_NUM_DELAY		1
#else
#define HC_UVC_ITD_FRAME_NUM_DELAY		0
#endif
#define HC_SOF_ISO_SIZE					1024
#define UVC_OHCI_ITD_NUM				10
#define UVC_GET_RP_CNT					1000	/* How many OHCI SOF count */
#define UVC_TASK_TIMEOUT				10		/* 100ms  */
#define UVC_TASK_WAIT_CNT				50		/* How many UVC_TASK_TIMEOUT */
#define UVC_FIRST_GET_RP_TICK			50		/* Wait for how many ticks then start to get RP information */

/* For USB host TX de-emphasis and RX equalizer I2C setting */
#define USB_I2C_TXDE_ADDR 0x18 
#define USB_I2C_RXEQ_ADDR 0x19

#define USBD_PHY_SETTING	45

typedef struct
{
	unsigned short	Width;
	unsigned short	Height;
} ST_Resolution;

typedef struct
{
	unsigned short	IMG_NUM;
	ST_Resolution	res[UVC_MAX_FRAME];
} ST_UVC_STILL_INFO;

typedef struct
{
	unsigned char	FrameIndex;
	ST_Resolution	res;
	unsigned char	FrameInterType;
	unsigned		MaxBuffer;
	unsigned		MinFrameInter;
	unsigned		MaxFrameInter;
	unsigned		FrameStep;
	unsigned		FrameInter[10];
} ST_UVC_FRAME_INFO;

typedef struct
{
	unsigned char		FormatIndex;
	unsigned char		FormatType;
	unsigned char		FrameTypeNum;
	ST_UVC_FRAME_INFO	FRAME_INFO[UVC_MAX_FRAME];
	ST_UVC_STILL_INFO	STILL_INFO;
} ST_UVC_FORMAT_INFO;

typedef struct
{
	unsigned char		FormatTypeNum;
	unsigned char		CaptureMode;
	ST_UVC_FORMAT_INFO	Format_INFO[UVC_MAX_FORMAT];
} ST_UVC_STREAM_INFO;

typedef struct
{
	unsigned char	format_index;
	unsigned char	frame_index;
	unsigned		buf_num;
	unsigned char	**buf;
	unsigned		ln;
} ST_UVC_PREVIEW_CTRL;

typedef struct
{
	unsigned		type;
	unsigned char	*buf;
	unsigned		ln;
} ST_UVC_CAPTURE;

typedef struct
{
	unsigned	Buf_Num;
	unsigned	ln;
} ST_UVC_FRAME_PASER;

/* USB Video Class Interface information */
typedef struct
{
	unsigned char	IF;			/* Interface Number */
	unsigned char	Alt_Num;	/* Alternative Interface Number */
	struct
	{
		unsigned char	Alt;	/* Alternative Interface Index */
		unsigned char	Endp;	/* Endpoint */
		unsigned short	MaxPkt; /* Maximum Packet Size */
	} alt[15];
	struct						/* Interrupt Endpoint Information */
	{
		unsigned char	Endp;	/* Endpoint */
		unsigned char	Poll;	/* Polling Interval */
		unsigned short	MaxPkt; /* Maximum Packet Size */
	} Int;
} ST_UVC_IF_INFO;

typedef struct
{
	ST_UVC_STREAM_INFO	STREAM_INFO;
	ST_UVC_IF_INFO		IF_INFO;
} ST_UVC_INFO;

typedef struct
{
	INT32U	abuf_addr;
	INT32U	bbuf_addr;
	INT32U	abuf_size;
	INT32U	bbuf_size;
} UVC_FRAME_BUF_INFO;

typedef struct
{
	INT32U	event;
	INT32U	buf;
} USBH_UVC_MSG_T;

typedef void (*USBH_L2_UVC_FRAME_DONE_CBK) (INT32U, INT32U, INT32U);

enum
{
	UVC_FRAME_NONE_EVENT,
	UVC_FRAME_A_DONE_EVENT,
	UVC_FRAME_A_OVERFLOW_EVENT,
	UVC_FRAME_B_DONE_EVENT,
	UVC_FRAME_B_OVERFLOW_EVENT,
	UVC_TASK_TIMEOUT_EVENT,
	UVC_FRAME_SEND_ITD_TIMEOUT_EVENT,
	UVC_SEND_SETUP_CMD_FAILED_EVENT,
	UVC_SEND_SETUP_CMD_SUCCESSFUL_EVENT,
	UVC_PORT_CONNECTED_EVENT,
	UVC_PORT_DISCONNECTED_EVENT,
	UVC_REVERSE_PARKING_STATUS_EVENT
};

enum
{
	UVC_APP_START_GET_FRAME_EVENT = 0x100,
	UVC_APP_STOP_GET_FRAME_EVENT,
	UVC_APP_STOP_GET_FRAME_TIMEOUT_EVENT,
	UVC_APP_SEND_FRAME_ITD_FAILED_EVENT,
	UVC_APP_SEND_SETUP_CMD_FAILED_EVENT,
	UVC_APP_SEND_SETUP_CMD_SUCCESSFUL_EVENT
};

enum
{
	UVC_DEV_STATE_DEVICE_NOT_FOUND = 0,
	UVC_DEV_STATE_DEVICE_PLUG_IN,
	UVC_DEV_STATE_DEVICE_READY,
	UVC_DEV_STATE_GETTING_JPEG,
	UVC_DEV_STATE_SEND_GET_FRAME_TIMEOUT,
	UVC_DEV_STATE_SEND_SETUP_CMD_FAILED
};

extern INT32U drv_l2_usbh_uvc_init(INT8U task_prio);
extern INT32U drv_l2_usbh_uvc_uninit(void);
extern INT32U drv_l2_usbh_uvc_enumeration(void);
extern INT32U drv_l2_usbh_uvc_start_get_frame(void);
extern void drv_l2_usbh_uvc_stop_get_frame(void);
extern void drv_l2_usbh_uvc_enable_get_reverse_parking_status(INT32U enable, INT32U timecnt);
extern INT32U drv_l2_usbh_uvc_get_reverse_parking_status(char* buf, INT32U* len);
extern void drv_l2_usbh_uvc_register_frame_done_cbk(USBH_L2_UVC_FRAME_DONE_CBK cbk);
extern void drv_l2_usbh_uvc_register_frame_info(UVC_FRAME_BUF_INFO *frame_info);
extern void drv_l2_usbh_uvc_update_frame_buf(UVC_FRAME_BUF_INFO *frame_info);
extern void drv_l2_usbh_ehci_set_empty_itd(void);
extern void drv_l2_usbh_ehci_uvc_register_frame_info(UVC_FRAME_BUF_INFO *frame_info);
extern void drv_l2_usbh_ehci_start_uvc_hw_iso_in(void);
extern void drv_l2_usbh_ehci_uvc_update_frame_buf(UVC_FRAME_BUF_INFO *frame_info);
extern INT32U drv_l2_usbh_ehci_hw_iso_in_trans(INT32U first_enter);
extern INT32U drv_l2_usbh_ehci_get_uvc_frame_start_addr(INT32U buf);
extern void drv_l2_usbh_ehci_uvc_init(void);
extern unsigned drv_l2_usbh_ehci_set_interface(INT32U *maxpkt);
extern void drv_l2_usbh_ehci_back_car_det(INT8U* data);
extern INT32U drv_l2_usbh_ehci_iso_in_trans(void);
extern void drv_l2_usbh_ehci_update_frame_list_itd(void);
extern INT32U drv_l2_usbh_ehci_enumeration(void);
extern INT8U drv_l2_usbh_uvc_verify(void);
extern void drv_l2_usbh_ehci_uvc_set_frame_size(INT16U w, INT16U h);
extern void drv_l2_usbh_uvc_set_frame_size(INT16U w, INT16U h);
extern INT32U drv_l2_usbh_uvc_get_frame_width(void);
extern INT32U drv_l2_usbh_uvc_get_frame_height(void);
extern void drv_l2_usbh_uvc_set_frame_format(INT32U format);
extern INT32U drv_l2_usbh_uvc_get_frame_format(void);

#endif /*__drv_l2_USBH_UVC_H__*/
